{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "01_pytorch_workflow_exercises.ipynb",
      "provenance": [],
      "collapsed_sections": [],
      "authorship_tag": "ABX9TyNYzatJtFkfUqqdiR6rYwVL",
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/mrdbourke/pytorch-deep-learning/blob/main/extras/exercises/01_pytorch_workflow_exercises.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "# 01. PyTorch Workflow Exercise Template\n",
        "\n",
        "The following is a template for the PyTorch workflow exercises.\n",
        "\n",
        "It's only starter code and it's your job to fill in the blanks.\n",
        "\n",
        "Because of the flexibility of PyTorch, there may be more than one way to answer the question.\n",
        "\n",
        "Don't worry about trying to be *right* just try writing code that suffices the question.\n",
        "\n",
        "You can see one form of [solutions on GitHub](https://github.com/mrdbourke/pytorch-deep-learning/tree/main/extras/solutions) (but try the exercises below yourself first!)."
      ],
      "metadata": {
        "id": "N8LsPXZti9Sw"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Import necessary libraries\n"
      ],
      "metadata": {
        "id": "Glu2fM4dkNlx"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Setup device-agnostic code\n"
      ],
      "metadata": {
        "id": "LqKhXY26m31s"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 1. Create a straight line dataset using the linear regression formula (`weight * X + bias`).\n",
        "  * Set `weight=0.3` and `bias=0.9` there should be at least 100 datapoints total. \n",
        "  * Split the data into 80% training, 20% testing.\n",
        "  * Plot the training and testing data so it becomes visual.\n",
        "\n",
        "Your output of the below cell should look something like:\n",
        "```\n",
        "Number of X samples: 100\n",
        "Number of y samples: 100\n",
        "First 10 X & y samples:\n",
        "X: tensor([0.0000, 0.0100, 0.0200, 0.0300, 0.0400, 0.0500, 0.0600, 0.0700, 0.0800,\n",
        "        0.0900])\n",
        "y: tensor([0.9000, 0.9030, 0.9060, 0.9090, 0.9120, 0.9150, 0.9180, 0.9210, 0.9240,\n",
        "        0.9270])\n",
        "```\n",
        "\n",
        "Of course the numbers in `X` and `y` may be different but ideally they're created using the linear regression formula."
      ],
      "metadata": {
        "id": "g7HUhxCxjeBx"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Create the data parameters\n",
        "\n",
        "\n",
        "# Make X and y using linear regression feature\n",
        "\n",
        "\n",
        "print(f\"Number of X samples: {len(X)}\")\n",
        "print(f\"Number of y samples: {len(y)}\")\n",
        "print(f\"First 10 X & y samples:\\nX: {X[:10]}\\ny: {y[:10]}\")"
      ],
      "metadata": {
        "id": "KbDG5MV7jhvE"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Split the data into training and testing\n"
      ],
      "metadata": {
        "id": "GlwtT1djkmLw"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Plot the training and testing data \n"
      ],
      "metadata": {
        "id": "29iQZFNhlYJ-"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 2. Build a PyTorch model by subclassing `nn.Module`. \n",
        "  * Inside should be a randomly initialized `nn.Parameter()` with `requires_grad=True`, one for `weights` and one for `bias`. \n",
        "  * Implement the `forward()` method to compute the linear regression function you used to create the dataset in 1. \n",
        "  * Once you've constructed the model, make an instance of it and check its `state_dict()`.\n",
        "  * **Note:** If you'd like to use `nn.Linear()` instead of `nn.Parameter()` you can."
      ],
      "metadata": {
        "id": "ImZoe3v8jif8"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Create PyTorch linear regression model by subclassing nn.Module"
      ],
      "metadata": {
        "id": "qzd__Y5rjtB8"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Instantiate the model and put it to the target device\n"
      ],
      "metadata": {
        "id": "5LdcDnmOmyQ2"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 3. Create a loss function and optimizer using `nn.L1Loss()` and `torch.optim.SGD(params, lr)` respectively. \n",
        "  * Set the learning rate of the optimizer to be 0.01 and the parameters to optimize should be the model parameters from the model you created in 2.\n",
        "  * Write a training loop to perform the appropriate training steps for 300 epochs.\n",
        "  * The training loop should test the model on the test dataset every 20 epochs."
      ],
      "metadata": {
        "id": "G6nYOrJhjtfu"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Create the loss function and optimizer\n"
      ],
      "metadata": {
        "id": "ltvoZ-FWjv1j"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Training loop\n",
        "\n",
        "\n",
        "# Train model for 300 epochs\n",
        "\n",
        "\n",
        "# Send data to target device\n",
        "\n",
        "\n",
        "for epoch in range(epochs):\n",
        "  ### Training\n",
        "\n",
        "  # Put model in train mode\n",
        "  \n",
        "\n",
        "  # 1. Forward pass\n",
        "  \n",
        "\n",
        "  # 2. Calculate loss\n",
        "  \n",
        "\n",
        "  # 3. Zero gradients\n",
        "  \n",
        "\n",
        "  # 4. Backpropagation\n",
        "  \n",
        "\n",
        "  # 5. Step the optimizer\n",
        "  \n",
        "\n",
        "  ### Perform testing every 20 epochs\n",
        "  if epoch % 20 == 0:\n",
        "\n",
        "    # Put model in evaluation mode and setup inference context \n",
        "    \n",
        "      # 1. Forward pass\n",
        "      \n",
        "      # 2. Calculate test loss\n",
        "\n",
        "      # Print out what's happening\n",
        "      print(f\"Epoch: {epoch} | Train loss: {loss:.3f} | Test loss: {test_loss:.3f}\")"
      ],
      "metadata": {
        "id": "xpE83NvNnkdV"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 4. Make predictions with the trained model on the test data.\n",
        "  * Visualize these predictions against the original training and testing data (**note:** you may need to make sure the predictions are *not* on the GPU if you want to use non-CUDA-enabled libraries such as matplotlib to plot)."
      ],
      "metadata": {
        "id": "x4j4TM18jwa7"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "# Make predictions with the model\n"
      ],
      "metadata": {
        "id": "bbMPK5Qjjyx_"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Plot the predictions (these may need to be on a specific device)\n"
      ],
      "metadata": {
        "id": "K3BdmQaDpFo8"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "## 5. Save your trained model's `state_dict()` to file.\n",
        "  * Create a new instance of your model class you made in 2. and load in the `state_dict()` you just saved to it.\n",
        "  * Perform predictions on your test data with the loaded model and confirm they match the original model predictions from 4."
      ],
      "metadata": {
        "id": "s2OnlMWKjzX8"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "from pathlib import Path\n",
        "\n",
        "# 1. Create models directory \n",
        "\n",
        "\n",
        "# 2. Create model save path \n",
        "\n",
        "# 3. Save the model state dict\n"
      ],
      "metadata": {
        "id": "hgxhgD14qr-i"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Create new instance of model and load saved state dict (make sure to put it on the target device)\n"
      ],
      "metadata": {
        "id": "P9vTgiLRrJ7T"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Make predictions with loaded model and compare them to the previous\n"
      ],
      "metadata": {
        "id": "8UGX3VebrVtI"
      },
      "execution_count": null,
      "outputs": []
    }
  ]
}